package org.dtrd.modules.record.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.RecordType;
import org.dtrd.modules.achievement.service.IDtrdEntRdSigninRecordService;
import org.dtrd.modules.record.entity.bean.DailyInsulinRecordBean;
import org.dtrd.modules.record.entity.bean.InsulinChart;
import org.dtrd.modules.record.entity.bean.InsulinRecordBean;
import org.dtrd.modules.record.entity.bean.CheckinRecord;
import org.dtrd.modules.record.entity.po.DtrdEntRdSigninInsulin;
import org.dtrd.modules.record.mapper.DtrdEntRdInsulinMapper;
import org.dtrd.modules.record.service.IInsulinRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;

import static org.dtrd.config.system.Constant.InsulinRecordType.*;

/**
 * @author 萧
 * @date:2021-08-22
 **/
@Service
@DS("multi-datasource1")
@Slf4j
public class InsulinRecordServiceImpl extends ServiceImpl<DtrdEntRdInsulinMapper, DtrdEntRdSigninInsulin> implements IInsulinRecordService {

    @Autowired
    private IDtrdEntRdSigninRecordService signinRecordService;

    @Override
    public DtrdEntRdSigninInsulin transformRecord(CheckinRecord checkinRecord) {
        DtrdEntRdSigninInsulin dt = new DtrdEntRdSigninInsulin().init();
        dt.setInsulinRemark(checkinRecord.getRemark());
        dt.setInsulinType(checkinRecord.getSubType());
        dt.setPatientId(checkinRecord.getPatientId());
        dt.setRecordTime(parseStringAsDateTime(checkinRecord.getRecordTime()));
        dt.setRecordDate(parseStringAsDate(checkinRecord.getRecordTime()));
        dt.setRecordPhoto(checkinRecord.getImages());
        dt.setInsulinInjection(checkinRecord.getInjection());
        dt.setInsulinDescribe(checkinRecord.getInsulinDescribe());
        return dt;
    }

    @Override
    public CheckinRecord transformPO(DtrdEntRdSigninInsulin po) {
        if (po == null) {
            return null;
        }
        CheckinRecord checkinRecord = new CheckinRecord();
        checkinRecord.setRecordTime(DateUtils.formatTime(po.getRecordTime()));
        checkinRecord.setRecordTimeHm(DateUtils.formatShortTime(po.getRecordTime()));
        checkinRecord.setDataId(po.getDataId());
        checkinRecord.setImages(po.getRecordPhoto());
        checkinRecord.setPatientId(po.getPatientId());
        checkinRecord.setRecordType(Constant.RecordType.INSULIN.getType());
        checkinRecord.setRecordTypeName(Constant.RecordType.INSULIN.getName());
        checkinRecord.setRemark(po.getInsulinRemark());
        return checkinRecord;
    }

    @Override
    public LambdaQueryWrapper<DtrdEntRdSigninInsulin> generateSelectRecordByDateQuery(Integer patientId,String date, Integer subType) {
        LambdaQueryWrapper<DtrdEntRdSigninInsulin> query = new LambdaQueryWrapper<>();
        query.eq(DtrdEntRdSigninInsulin::getIsDel, 0)
                .eq(DtrdEntRdSigninInsulin::getPatientId,patientId)
                .eq(DtrdEntRdSigninInsulin::getRecordDate, date).eq(DtrdEntRdSigninInsulin::getInsulinType, subType);
        return query;
    }

    @Override
    public boolean saveOrUpdateInsulinRecord(InsulinRecordBean insulinInfo) {
        DtrdEntRdSigninInsulin po = new DtrdEntRdSigninInsulin();
        if (insulinInfo.getDataId() == null) {
            po = po.init();
        }
        po = po.parseFromDTO(insulinInfo);
        String recordTime = insulinInfo.getRecordTime();
        Date recordDate = null;
        try {
            recordDate = DateUtils.parseDate(recordTime, DateUtils.date_sdf.get().toPattern());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        LambdaUpdateWrapper<DtrdEntRdSigninInsulin> wrapper = Wrappers.lambdaUpdate(DtrdEntRdSigninInsulin.class)
                .eq(DtrdEntRdSigninInsulin::getRecordDate, recordDate)
                .eq(DtrdEntRdSigninInsulin::getPatientId, insulinInfo.getPatientId())
                .eq(DtrdEntRdSigninInsulin::getInsulinType, insulinInfo.getInsulinType());
        boolean result = saveOrUpdate(po, wrapper);
        log.info("InsulinRecordServiceImpl.saveOrUpdateInsulinRecord.[insulinInfo] after save result==" + result + ";patientId=" + insulinInfo.getPatientId() + "; dataId=" + po.getDataId());
        // 补充打卡记录
        if (po.getDataId() == null) {
            po = getOne(wrapper);
        }
        signinRecordService.saveSigninRecord(po.getDataId(), insulinInfo.getInsulinType(), mapper ->
                mapper.apply(insulinInfo.getPatientId())
                        .withRecordType(RecordType.INSULIN.getType())
                        .withRecordTime(recordTime)
                        .withRecordValue(insulinInfo.getInjection()+"")
                        .withRecordDesc(insulinInfo.getInsulinDescribe())
                        .withImages(insulinInfo.getRecordPhoto())
                        .build()
        );
//        DtrdEntRdSigninInsulin po = getOne(wrapper);
//        signinRecordService.saveSigninRecord(po.getDataId(),
//                po.getPatientId(),
//                Constant.RecordType.INSULIN.getType(),
//                insulinInfo.getInsulinType(),
//                DateUtils.formatDate(recordDate, DateUtils.date_sdf.get().toPattern()));
        return result;
    }

    @Override
    public Integer getInsulinRecordDataCount(Integer patientId, String startDate, String endDate) {
        return baseMapper.countGroupInsulinRecord(patientId, startDate, endDate);
    }

    @Override
    public List<DailyInsulinRecordBean> getAllGroupedInsulinRecord(Integer patientId, String startDate, String endDate, Integer page, Integer pageSize) {
        List<DtrdEntRdSigninInsulin> list = baseMapper.getAllGroupedInsulinRecord(patientId, startDate, endDate);
        if (list.size() > 0) {
            List<DailyInsulinRecordBean> dataList = new ArrayList<>(list.size() / 2);
            TreeMap<String, List<DtrdEntRdSigninInsulin>> recordMap = new TreeMap<>(Collections.reverseOrder());
            list.forEach(value -> {
                String date = DateUtils.formatDate(value.getRecordDate());
                List<DtrdEntRdSigninInsulin> dataRecordList = recordMap.get(date);
                if (dataRecordList == null) {
                    dataRecordList = new ArrayList<>(4);
                }
                dataRecordList.add(value);
                recordMap.put(date, dataRecordList);
            });
            if (MapUtil.isNotEmpty(recordMap)) {
                Set<String> keySet = recordMap.keySet();
                keySet.forEach(date -> {
                    DailyInsulinRecordBean dailyInsulinRecordBean = new DailyInsulinRecordBean();
                    dailyInsulinRecordBean.setDate(date);
                    dailyInsulinRecordBean.setPatientId(patientId);
                    List<DtrdEntRdSigninInsulin> dataRecord = recordMap.get(date);
                    for (DtrdEntRdSigninInsulin insulinRecord : dataRecord) {
                        Constant.InsulinRecordType insulinType = Constant.InsulinRecordType.valueOf(insulinRecord.getInsulinType());
                        assert insulinType != null;
                        switch (insulinType) {
                            case MORNING:
                                dailyInsulinRecordBean.setMorningInsulinDescribe(insulinRecord.getInsulinDescribe());
                                dailyInsulinRecordBean.setMorningInsulinRecord(new InsulinRecordBean().parseFromPo(insulinRecord));
                                break;
                            case NOON:
                                dailyInsulinRecordBean.setNoonInsulinDescribe(insulinRecord.getInsulinDescribe());
                                dailyInsulinRecordBean.setNoonInsulinRecord(new InsulinRecordBean().parseFromPo(insulinRecord));
                                break;
                            case EVENING:
                                dailyInsulinRecordBean.setNightInsulinDescribe(insulinRecord.getInsulinDescribe());
                                dailyInsulinRecordBean.setNightInsulinRecord(new InsulinRecordBean().parseFromPo(insulinRecord));
                                break;
                            case SLEEP:
                                dailyInsulinRecordBean.setBeforeSleepInsulinDescribe(insulinRecord.getInsulinDescribe());
                                dailyInsulinRecordBean.setBeforeSleepInsulinRecord(new InsulinRecordBean().parseFromPo(insulinRecord));
                                break;
                            case DEVICE:
                                dailyInsulinRecordBean.setCasInsulinDescribe(insulinRecord.getInsulinDescribe());
                                dailyInsulinRecordBean.setCasInsulinRecord(new InsulinRecordBean().parseFromPo(insulinRecord));
                                break;
                            default:
                                break;
                        }
                    }
                    dataList.add(dailyInsulinRecordBean);
                });
                // 处理分页
                assert page != null;
                assert pageSize != null;
                int pageStart = (page-1) * pageSize;
                ArrayList<DailyInsulinRecordBean> resultList = new ArrayList<>(pageSize);
                int range = Math.min(page * pageSize, dataList.size());
                for (int i = pageStart; i < range; i++) {
                    resultList.add(dataList.get(i));
                }
                return resultList;
            }
        }
        return null;
    }

    @Override
    public InsulinChart getInsulinRecordsForChart(int patientId, String startDate, String endDate) {
        List<DtrdEntRdSigninInsulin> poList = baseMapper.selectInsulinRecordsForChart(patientId, startDate, endDate);
        if (poList.size() == 0) {
            return null;
        }
        List<String> recordDateList = new ArrayList<>(poList.size());
        List<String> morningInsulinList = new ArrayList<>(poList.size());
        List<String> noonInsulinList = new ArrayList<>(poList.size());
        List<String> nightInsulinList = new ArrayList<>(poList.size());
        List<String> beforeSleepInsulinList = new ArrayList<>(poList.size());
        List<String> allInsulinList = new ArrayList<>(poList.size());
        List<String> recordTimeList = new ArrayList<>(poList.size());
        String recordDate, recordTime;
        // 这里用linkedHashMap , 不打乱 date 的排序
        Map<String, List<DtrdEntRdSigninInsulin>> recordMap = new LinkedHashMap<>();
        // 这里先默认记录项都不缺失
        for (DtrdEntRdSigninInsulin insulinRecord : poList) {
            recordDate = DateUtils.formatDate(insulinRecord.getRecordDate());
            recordTime = DateUtils.formatDate(insulinRecord.getRecordTime(), DateUtils.datetimeFormat.get().toPattern());
            allInsulinList.add(insulinRecord.getInsulinDescribe());
            recordTimeList.add(recordTime);
            List<DtrdEntRdSigninInsulin> datePoList = recordMap.get(recordDate);
            if (datePoList == null) {
                datePoList = new ArrayList<>(4);
            }
            datePoList.add(insulinRecord);
            recordMap.put(recordDate, datePoList);
        }
        Set<String> keySet = recordMap.keySet();
        for (String date : keySet) {
            recordDateList.add(date);
            List<DtrdEntRdSigninInsulin> datePoList = recordMap.get(date);
            for (DtrdEntRdSigninInsulin insulin : datePoList) {
                if (insulin.getInsulinType().equals(MORNING.getType())) {
                    morningInsulinList.add(insulin.getInsulinDescribe());
                }
                if (insulin.getInsulinType().equals(NOON.getType())) {
                    noonInsulinList.add(insulin.getInsulinDescribe());
                }
                if (insulin.getInsulinType().equals(EVENING.getType())) {
                    nightInsulinList.add(insulin.getInsulinDescribe());
                }
                if (insulin.getInsulinType().equals(SLEEP.getType())) {
                    beforeSleepInsulinList.add(insulin.getInsulinDescribe());
                }
            }
        }
        InsulinChart insulinChart = new InsulinChart();
        insulinChart.setRecordDateList(recordDateList);
        insulinChart.setMorningInsulinList(morningInsulinList);
        insulinChart.setNoonInsulinList(noonInsulinList);
        insulinChart.setNightInsulinList(nightInsulinList);
        insulinChart.setBeforeSleepInsulinList(beforeSleepInsulinList);
        insulinChart.setAllInsulinList(allInsulinList);
        insulinChart.setRecordTimeList(recordTimeList);
        return insulinChart;
    }
}
